#include <iostream>
#include <string>
#include <memory>

namespace mySmPtr
{
    template <typename T>
    class auto_ptr
    {
    public:
        auto_ptr(T* ptr):_ptr(ptr) {}
        ~auto_ptr() { delete _ptr; }

        auto_ptr(auto_ptr &ap)
        {
            /*转移管理权*/
            _ptr = ap._ptr;
            ap.ptr = nullptr;
        }

        auto_ptr& operator=(auto_ptr &ap)
        {
            if(this != &ap) {
                if(_ptr) delete _ptr;
                _ptr = ap._ptr;
                ap._ptr = nullptr;
            }
            return *this;
        }
        
        T& operator*() { return *_ptr; }
        T* operator->() { return _ptr; }
    private:
        T* _ptr;
    };

    template <typename T>
    class unique_ptr
    {
    public:
        unique_ptr(T* ptr): _ptr(ptr) {}
        ~unique_ptr() { if(_ptr) delete _ptr; }

        unique_ptr(const unique_ptr& up) = delete;
        unique_ptr& operator=(const unique_ptr& up) = delete;

        unique_ptr(unique_ptr&& up): _ptr(up._ptr) { up._ptr = nullptr; }
        unique_ptr&& operator=(unique_ptr&& up) 
        { 
            if(this != &up) std::swap(_ptr, up._ptr); 
            return *this;
        }

        T& operator*() { return *_ptr; }
        T* operator->() { return _ptr; }
    private:
        T* _ptr;
    };

    //template <typename T>
    //class shared_ptr
    //{
    //public:
    //    shared_ptr(T* ptr):_ptr(ptr), _count(new int(1)) {}
    //    ~shared_ptr()
    //    {
    //        release();
    //    }

    //    shared_ptr(const shared_ptr& sp):_ptr(sp._ptr), _count(sp._count)
    //    {
    //        (*_count)++;
    //    }
    //    shared_ptr& operator=(const shared_ptr& sp)
    //    {
    //        if(this != &sp) {
    //            release();
    //            _ptr = sp;
    //            _count = sp._count;
    //            (*_count)++;
    //        }
    //        return *this;
    //    }

    //    T& operator*() { return *_ptr; }
    //    T* operator->() { return _ptr; }
    //private:
    //    void release()
    //    {
    //        if(--(*_count) == 0) {
    //            delete _ptr;
    //            delete _count;
    //        }
    //    }
    //private:
    //    T* _ptr;
    //    int* _count;
    //};

    struct control_block
    {
        int _share_count;
        int _weak_count;
    };

    // 前置声明
    template <typename T>
    class weak_ptr;

    template <typename T>
    class shared_ptr
    {
    public:
        shared_ptr(T* ptr)
            :_ptr(ptr), _ctrl_block(new control_block)
        {
            _ctrl_block->_share_count = 1;
            _ctrl_block->_weak_count = 0;
        }
        ~shared_ptr() { release(); }

        shared_ptr(const shared_ptr& sp)
            :_ptr(sp._ptr), _ctrl_block(sp._ctrl_block)
        {
            if(_ctrl_block) {
                _ctrl_block->_share_count++;
            }
        }

        shared_ptr& operator=(const shared_ptr& sp)
        {
            if(this != &sp) {
                release();
                _ptr = sp._ptr;
                _ctrl_block = sp._ctrl_block;
                _ctrl_block->_share_count++;
            }
            return *this;
        }

        T& operator*() { return *_ptr; }
        T* operator->() { return _ptr; }
    private:
        void release()
        {
            if(_ctrl_block) {
                _ctrl_block->_share_count--;
                /*共享计数为0，释放该资源，控制块的释放交给weak_ptr*/
                if(_ctrl_block->_share_count == 0) {
                    delete _ptr;
                    if(_ctrl_block->_weak_count == 0) {
                        delete _ctrl_block;
                    }
                }
                _ptr = nullptr;
                _ctrl_block = nullptr;
            }
        }
        friend class weak_ptr<T>;

        T* _ptr;
        control_block* _ctrl_block;
    };

    template <typename T>
    class weak_ptr
    {
        friend class shared_ptr<T>;
    public:
        weak_ptr(const shared_ptr<T>& sp)
            :_ptr(sp._ptr), _ctrl_block(sp._ctrl_block)
        {
            if(_ctrl_block) {
                _ctrl_block->_weak_count++;
            }
        }

        ~weak_ptr() { release(); }

        /*拷贝构造，共享计数不变，弱引用++*/
        weak_ptr(const weak_ptr& wp)
            :_ptr(wp._ptr), _ctrl_block(wp._ctrl_block)
        {
            if(_ctrl_block) {
                _ctrl_block->_weak_count++;
            }
        }

        /*拷贝赋值，释放原弱引用，指向新资源，更新控制块，弱引用++*/
        weak_ptr& operator=(const weak_ptr& wp)
        {
            if(this != &wp) {
                release();
                _ptr = wp._ptr;
                _ctrl_block = wp._ctrl_block;
                if(_ctrl_block)
                    _ctrl_block->_weak_count++;
            }
            return *this;
        }

        /* 控制块为空，或者共享计数为0，该资源已过期 */
        bool expired() { return !_ctrl_block || _ctrl_block->_share_count == 0; }

        shared_ptr<T> lock() const;
    private:
        void release()
        {
            if(_ctrl_block) {
                _ctrl_block->_weak_count--;
                /*共享计数和弱引用都为0，删除控制块*/
                if(_ctrl_block->_share_count == 0 && _ctrl_block->_weak_count == 0) {
                    delete _ctrl_block;
                }
                _ptr = nullptr;
                _ctrl_block = nullptr;
            }
        }
    private:
        T* _ptr;
        control_block* _ctrl_block;
    };

    template <typename T>
    shared_ptr<T> weak_ptr<T>::lock() const
    {
        if(expired()) return shared_ptr<T>(nullptr);
        // 创建一个新的shared_ptr指向该资源，并返回
        shared_ptr<T> ret;
        ret._ptr = _ptr;
        ret._ctrl_block = _ctrl_block;
        _ctrl_block->_share_count++;
        return ret;
    }
}

//int main()
//{
//    std::unique_ptr<int[]> p1(new int[2]{1, 2});
//    std::cout << p1[0] << " " << p1[1] << std::endl;
//
//    std::shared_ptr<int[]> p2(new int[5]{1, 2, 3, 4, 5});
//    std::cout << p2[0] << " " << p2[4] << std::endl;
//
//    return 0;
//}


template <typename T>
struct DeleteFunc
{
    void operator()(T* p)
    {
        delete[] p;
    }
};

template <typename T>
void deleteforarr(T* t)
{
    delete[] t;
}

//int main()
//{
//    // 仿函数做删除器
//    // 模板参数必须传，参数可传可不传
//	std::unique_ptr<int, DeleteFunc<int>> up1(new int[10], DeleteFunc<int>());
//	std::unique_ptr<int, DeleteFunc<int>> up2(new int[10]);
//
//    // lambda做删除器
//    // 模板参数也得传，但因为无法拿到lambda的类型，所以我们使用decltype关键字获取lambda的类型
//    // 构造参数不可省略
//    auto erase = [](int* arr){
//        delete[] arr;
//    };
//    std::unique_ptr<int, decltype(erase)> up3(new int[3], erase);
//
//    // 函数指针做删除器
//    std::unique_ptr<int, void(*)(int*)> up4(new int[4], deleteforarr<int>);
//
//    return 0;
//}

//int main()
//{
//    // 仿函数做删除器
//    std::shared_ptr<int> sp1(new int[10], DeleteFunc<int>());
//    
//    // lambda做删除器
//    std::shared_ptr<int> sp2(new int[10], [](int* ptr) {delete[] ptr; });
//    
//    // 函数指针做删除器
//    std::shared_ptr<int> sp3(new int[10], deleteforarr<int>);
//
//    return 0;
//}


#include <iostream>
#include <string>
#include <typeinfo>

// C语言风格的格式转换
int main1()
{
	int i = 1;
	// 隐式类型转换
	// 隐式类型转换主要发生在整形和整形之间，整形和浮点数之间，浮点数和浮点数之间
	double d = i;
	printf("%d, %.2f\n", i, d);

	int* p = &i;
	// 显示的强制类型转换
	// 强制类型转换主要发生在指针和整形之间，指针和指针之间
    // g++编译器下也不允许
	//int address = (int)p;
	//printf("%p, %d\n", p, address);

	// 编译报错：类型强制转换: 无法从“int *”转换为“double”
	// 指针是地址的编号，也是一种整数，所以可以和整形互相转换
	// 但是指针和浮点数毫无关联，强转也是不支持的
	//d = (double)p;

	return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

// C++风格的类型转换
class A
{
public:
    A(int x) :_a(x) {}
    A(int x, int y) :_a(x), _b(y) {}
    operator int() { return _a + _b; }
private:
    int _a;
    int _b;
};

class B
{
public:
    B(const A) {}
private:
    std::string s;
};

// 1.内置类型转换为自定义类型
int main2()
{
    // C++中，内置类型转换为自定义类型，需要有构造函数支持
    // 隐式类型转换，本质上是由1构造了一个临时对象，然后进行拷贝构造，编译器优化为一个构造
    A aa = 1; 

    // 多参数进行隐式类型转换要使用花括号
    A aa1 = {1, 2};
    return 0;
}

// 2.自定义类型转换为内置类型，需要自定义类型重载operator()
// 但是这里重载operator()时需要进行特殊处理，格式为operator type(){}
int main3()
{
    A aa = 1;
    int b = aa; // 没有operator int() 成员函数，就会报错
    return 0;
}

// 3.自定义类型之间也可以进行转化，只需要有特定参数的构造函数即可
// 如果想让A转化为B，则需要在B中实现以A为参数的构造函数
int main4()
{
    A aa = {1, 2};
    B b = aa;
    return 0;
}

class people
{
    virtual void get() {}
private:
    std::string _name;
};

class student : public people
{};

// 4.C/C++不是类型安全的语言，因为其支持类型转换
// C++规范了显示类型转换的方式
//int main()
//{
//    // static_cast<>() 用于两个含义相近的类型进行转换，要求转换是有意义的
//    // 基本类型之间的转换， 或者有继承关系的类之间进行转换
//    // 比如：int->double, 两者都是表示数值大小，可以进行转换
//    int a = 10;
//    double b = static_cast<double>(a);
//    std::cout << "a->" << typeid(a).name() << std::endl;
//    std::cout << "b->" << typeid(b).name() << std::endl;
//
//    // reinterpret_cast 用于进行底层的类型转换，将一种类型的指针或引用转换为另一种类型，不进行类型检查，风险较高。
//    int *ptr = &a;
//    double *d_ptr = reinterpret_cast<double*>(ptr); // 将int* 转换为 double*
//    std::cout << "ptr->" << typeid(ptr).name() << std::endl;
//    std::cout << "d_ptr->" << typeid(d_ptr).name() << std::endl;
//
//    // const_cast 用于取出指针/引用的const属性，或者添加const属性
//    volatile const int c = 100; // 如果不加volatile关键字，编译器识别到const，就会将其直接放在寄存器中，而不从内存中读取
//    int * c_ptr = const_cast<int*>(&c);
//    *c_ptr = 1;
//    std::cout << "c->" << c << std::endl;
//    std::cout << "c_ptr->" << *c_ptr << std::endl;
//
//    // dynamic_cast 用于基类和派生类之间指针/引用的转换，要求基类必须是多态类型——有虚函数
//    // 如果是派生类转换为基类，则转化成功
//    // 如果是基类转化为派生类，转化失败，指针转化返回nullptr， 引用转化抛出异常bad_cast
//    student *s = new student();
//    people *p = dynamic_cast<people*>(s);
//    
//    // 因为多态类型，有虚函数表，在底层可以用虚表中的type_info来判断指向的是基类的指针还是派生类的指针
//
//    return 0;
//}


int main()
{
    std::string s;
    std::cout << sizeof(s) << std::endl;
    return 0;
}